package com.slashvision.im.chat

import android.os.CountDownTimer
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Popup
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
import com.slashvision.im.R
import com.slashvision.im.SLog
import com.slashvision.im.ui.UImage
import com.slashvision.im.ui.UText
import com.slashvision.im.ui.myCoilPainter
import io.openim.android.sdk.enums.MessageType
import io.openim.android.sdk.models.Message
import java.io.File

/**
 * author : lizhenxin
 *  date  : 2021/11/16
 *  desc  :
 */

/**
 * 消息列表
 */
@ExperimentalComposeUiApi
@Composable
fun MsgList(
    modifier: Modifier = Modifier,
    scrollState: LazyListState,
    data: List<Message>,
    friendId: String,
    onClickAvatar: () -> Unit,
    onMessageClickListener: OnMessageClickListener,
) {
    val msgListState = remember {
        mutableStateListOf<Message>().apply {
            addAll(data)
        }
    }
    Box(modifier = modifier) {
        LazyColumn(
            state = scrollState,
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Bottom,
            reverseLayout = true
        ) {
            SLog.d("ChatViewModel", "${data.size}")
            items(msgListState.asReversed()) { item ->
                MessageItem(
                    isSend = item.sendID != friendId,
                    msg = item,
                    onClickAvatar = onClickAvatar,
                    onMsgClick = {
                        onMessageClickListener.onClick(item)
                    },
                    onCopyClick = {
                        onMessageClickListener.onCopyClick(item)
                    },
                    onDeleteClick = {
                        onMessageClickListener.onDeleteClick(item)
                    }
                )
            }
        }
    }
}


/**
 * 每一项消息的分发器
 */
@ExperimentalComposeUiApi
@Composable
fun MessageItem(
    isSend: Boolean,
    msg: Message,
    onClickAvatar: () -> Unit,
    onMsgClick: (Message) -> Boolean,
    onCopyClick: (Message) -> Unit,
    onDeleteClick: (Message) -> Unit
) {
    if (!isSend) {
        MsgItemRec(
            msg = msg,
            onClickAvatar = onClickAvatar,
            onMsgClick = onMsgClick,
            onCopyClick = onCopyClick,
            onDeleteClick = onDeleteClick
        )
    } else {
        MsgItemSend(
            msg = msg,
            onClickAvatar = onClickAvatar,
            onMsgClick = onMsgClick,
            onCopyClick = onCopyClick,
            onDeleteClick = onDeleteClick
        )
    }
}


/**
 * 接收消息项
 */
@ExperimentalComposeUiApi
@Composable
fun MsgItemRec(
    msg: Message,
    onClickAvatar: () -> Unit,
    onMsgClick: (Message) -> Boolean,
    onCopyClick: (Message) -> Unit,
    onDeleteClick: (Message) -> Unit
) {

    val longPressedState = remember { mutableStateOf(false) }

    var msgBoxSize: IntSize = IntSize.Zero

    val voicePlayState = remember { mutableStateOf(false) }
    Box {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 11.dp, horizontal = 16.dp)
        ) {
            Image(
                painter = painterResource(id = R.drawable.default_avatar),
                contentDescription = null,
                modifier = Modifier
                    .size(40.dp)
                    .clip(CircleShape)
                    .clickable { onClickAvatar() }
            )
            Spacer(modifier = Modifier.width(8.dp))
            Row(modifier = Modifier
                .pointerInput(Unit) {
                    this.detectTapGestures(
                        onTap = {
                            onMsgClick(msg)
                            if (msg.contentType == MessageType.VOICE) {
                                voicePlayState.value = !voicePlayState.value
                            }
                        },
                        onLongPress = {
                            longPressedState.value = !longPressedState.value
                        }
                    )
                }) {
                when (msg.contentType) {
                    MessageType.TEXT -> MsgItemText(msg, false, onSized = { msgBoxSize = it })
                    MessageType.PICTURE -> MsgItemImage(msg = msg, isSend = false) { msgBoxSize = it }
                    MessageType.VOICE -> MsgItemVoice(
                        msg = msg,
                        isSend = false,
                        onClick = { onMsgClick(it) }) { msgBoxSize = it }
                    MessageType.VIDEO -> MsgItemVideo(msg = msg, isSend = false) { msgBoxSize = it }
                    MessageType.TYPING -> MsgItemTime(msg = msg)
                }
            }
            Spacer(modifier = Modifier.width(8.dp))
            msg.takeIf { it.status == 3 }
                ?.let {
                    UImage(
                        drawableId = R.drawable.ic_im_fail,
                        width = 20.dp,
                        height = 20.dp,
                        modifier = Modifier
                            .align(
                                Alignment.CenterVertically
                            )
                            .clickable { onMsgClick(msg) }
                    )
                }

            Spacer(modifier = Modifier.weight(1f))
        }

//    错位，跑到屏幕左上角了
        if (longPressedState.value) {
            MsgOption(msg = msg,
                state = longPressedState,
                alignment = Alignment.TopStart,
                offset = IntOffset(msgBoxSize.width, -msgBoxSize.height - 150),
                onCopyClick = {
                    onCopyClick(msg)
                    longPressedState.value = !longPressedState.value
                },
                onDeleteClick = {
                    onDeleteClick(msg)
                    longPressedState.value = !longPressedState.value
                })
        }
    }
}


/**
 * 发送消息项
 */
@ExperimentalComposeUiApi
@Composable
fun MsgItemSend(
    msg: Message,
    onClickAvatar: () -> Unit,
    onMsgClick: (Message) -> Boolean,
    onCopyClick: (Message) -> Unit,
    onDeleteClick: (Message) -> Unit
) {
    val longPressedState = remember { mutableStateOf(false) }

    var msgBoxSize: IntSize = IntSize.Zero

    val voicePlayState = remember {
        mutableStateOf(false)
    }

    Box(modifier = Modifier.wrapContentSize()) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 11.dp, horizontal = 16.dp)
        ) {


            Spacer(modifier = Modifier.weight(1f))

            msg.takeIf { it.status == 3 }
                ?.let {
                    UImage(
                        drawableId = R.drawable.ic_im_fail,
                        width = 20.dp,
                        height = 20.dp,
                        modifier = Modifier
                            .align(
                                Alignment.CenterVertically
                            )
                            .clickable { onMsgClick(msg) }
                    )
                }
            Spacer(modifier = Modifier.width(8.dp))
            // 消息内容
            Row(horizontalArrangement = Arrangement.End,
                modifier = Modifier
                    .pointerInput(Unit) {
                        this.detectTapGestures(
                            onTap = {
                                onMsgClick(msg)
                                if (msg.contentType == MessageType.VOICE) {
                                    voicePlayState.value = !voicePlayState.value
                                }
                            },
                            onLongPress = {
                                longPressedState.value = !longPressedState.value
                            }
                        )
                    }) {
                when (msg.contentType) {
                    MessageType.TEXT -> MsgItemText(msg, true, onSized = { msgBoxSize = it })
                    MessageType.PICTURE -> MsgItemImage(msg = msg, isSend = true) { msgBoxSize = it }
                    MessageType.VOICE -> MsgItemVoice(
                        msg = msg,
                        isSend = true,
                        onClick = { onMsgClick(it) }) { msgBoxSize = it }
                    MessageType.VIDEO -> MsgItemVideo(msg = msg, isSend = true) { msgBoxSize = it }
                    MessageType.TYPING -> MsgItemTime(msg = msg)
                }
            }
            Spacer(modifier = Modifier.width(8.dp))
// 头像
            Image(
                painter = painterResource(id = R.drawable.default_avatar),
                contentDescription = null,
                modifier = Modifier
                    .size(40.dp)
                    .clip(CircleShape)
                    .clickable { onClickAvatar() }
            )
        }
        if (longPressedState.value) {
            MsgOption(msg = msg,
                state = longPressedState,
                offset = IntOffset(msgBoxSize.width, -msgBoxSize.height - 150),
                alignment = Alignment.TopEnd,
                onCopyClick = {
                    onCopyClick(msg)
                    longPressedState.value = !longPressedState.value
                },
                onDeleteClick = {
                    onDeleteClick(msg)
                    longPressedState.value = !longPressedState.value
                })
        }
    }
}

/**
 * 时间消息
 */
@Composable
fun MsgItemTime(msg: Message) {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 11.dp)
    ) {
        Text(
            text = msg.content,
            fontSize = 12.sp,
            color = colorResource(id = R.color.black_7),
            modifier = Modifier.align(Alignment.Center)
        )
    }
}

/**
 * 文字消息
 */
@Composable
fun MsgItemText(msg: Message, isSend: Boolean, onSized: (IntSize) -> Unit) = Text(
    text = msg.content,
    fontSize = 13.sp,
    color = colorResource(id = if (isSend) R.color.white else R.color.black_3),
    textAlign = TextAlign.End,
    modifier = Modifier
        .wrapContentWidth()
        .background(
            color = colorResource(id = if (isSend) R.color.main_blue else R.color.color_f7),
            shape = RoundedCornerShape(20.dp)
        )
        .padding(vertical = 10.dp, horizontal = 16.dp)
        .onGloballyPositioned {
            onSized(it.size)
        }
)

/**
 * 图片消息
 */
@Composable
fun MsgItemImage(msg: Message, isSend: Boolean, onSized: (IntSize) -> Unit) = Image(
    painter = myCoilPainter(request = msg.pictureElem.snapshotPicture.url),
    contentDescription = null,
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(173.dp)
        .clip(RoundedCornerShape(15.dp))
        .onGloballyPositioned {
            onSized(it.size)
        }
)

/**
 * 视频消息
 */
@Composable
fun MsgItemVideo(msg: Message, isSend: Boolean, onSized: (IntSize) -> Unit) = Box(
    modifier = Modifier
        .wrapContentSize()
) {
    Box(modifier = Modifier.wrapContentSize()) {
        Image(
            painter = myCoilPainter(request = if (isSend) File(msg.videoElem.snapshotPath) else msg.videoElem.snapshotUrl),
            contentDescription = null,
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .clip(RoundedCornerShape(15.dp))
                .size(173.dp)
                .onGloballyPositioned {
                    onSized(it.size)
                }
        )
        Image(
            painter = painterResource(id = R.drawable.ic_chat_video),
            contentDescription = null,
            modifier = Modifier.align(Alignment.Center)
        )
    }
}


/**
 * 语音消息
 */
@Composable
fun MsgItemVoice(
    msg: Message,
    isSend: Boolean,
    onClick: (Message) -> Boolean,       // 返回是否播放
    onSized: (IntSize) -> Unit
) {
    check(msg.contentType == MessageType.VOICE)


    val countDownState = remember {
        mutableStateOf(-1)
    }

    val countDownTimer = object : CountDownTimer(msg.soundElem.duration.toInt() * 1000L, 500) {
        override fun onTick(millisUntilFinished: Long) {
            countDownState.value -= 1
        }

        override fun onFinish() {
            countDownState.value = -1
        }
    }

    if (isSend) {
        Box(modifier = Modifier
            .wrapContentWidth()
            .background(
                color = colorResource(id = R.color.main_blue),
                shape = RoundedCornerShape(20.dp)
            )
            .clickable {
                val state = onClick(msg)
                if (state) {
                    countDownState.value = msg.soundElem.duration.toInt()
                    countDownTimer.start()
                } else {
                    countDownTimer.cancel()
                    countDownState.value = -1
                }
            }
            .onGloballyPositioned { onSized(it.size) }) {
            ConstraintLayout(
                modifier = Modifier.padding(
                    vertical = 10.dp,
                    horizontal = 16.dp
                )
            ) {
                val rText = createRef()
                val rIcon = createRef()
                Image(
                    painter = painterResource(
                        id = getRecvIconRes(countDownState.value)
                    ),
                    contentDescription = null,
                    modifier = Modifier
                        .constrainAs(rIcon) {
                            end.linkTo(parent.end)
                            centerVerticallyTo(parent)
                        }
                        .size(13.dp)
                )
                Text(
                    text = "${msg.soundElem.duration}''",
                    fontSize = 13.sp,
                    color = colorResource(id = R.color.white),
                    maxLines = 1,
                    modifier = Modifier.constrainAs(rText) {
                        centerVerticallyTo(parent)
                        start.linkTo(parent.start, 76.dp)
                        end.linkTo(rIcon.start, 8.dp)
                        width = Dimension.wrapContent
                        height = Dimension.wrapContent
                    }
                )
            }
        }
    } else {
        Box(modifier = Modifier
            .wrapContentWidth()
            .background(
                color = colorResource(id = R.color.color_f7),
                shape = RoundedCornerShape(20.dp)
            )
            .clickable {
                val state = onClick(msg)
                if (state) {
                    countDownState.value = msg.soundElem.duration.toInt()
                    countDownTimer.start()
                } else {
                    countDownTimer.cancel()
                    countDownState.value = -1
                }
            }
            .onGloballyPositioned { onSized(it.size) }) {
            ConstraintLayout(
                modifier = Modifier.padding(
                    vertical = 10.dp,
                    horizontal = 16.dp
                )
            ) {
                val rText = createRef()
                val rIcon = createRef()
                Image(
                    painter = painterResource(id = getSendIconRes(countDownState.value)),
                    contentDescription = null,
                    modifier = Modifier
                        .constrainAs(rIcon) {
                            start.linkTo(parent.start)
                            centerVerticallyTo(parent)
                        }
                        .size(13.dp)
                )
                Text(
                    text = "${msg.soundElem.duration}''",
                    fontSize = 13.sp,
                    color = colorResource(id = R.color.black_3),
                    maxLines = 1,
                    modifier = Modifier.constrainAs(rText) {
                        centerVerticallyTo(parent)
                        start.linkTo(rIcon.end, 8.dp)
                        end.linkTo(parent.end, 76.dp)
                        width = Dimension.wrapContent
                        height = Dimension.wrapContent
                    }
                )
            }
        }
    }
}

fun getSendIconRes(index: Int) = when (index % 3) {
    0 -> R.drawable.ic_voice_left_3
    1 -> R.drawable.ic_voice_left_2
    2 -> R.drawable.ic_voice_left_1
    else -> R.drawable.ic_voice_left_3
}


fun getRecvIconRes(index: Int) = when (index % 3) {
    0 -> R.drawable.ic_voice_right_3
    1 -> R.drawable.ic_voice_right_2
    2 -> R.drawable.ic_voice_right_1
    else -> R.drawable.ic_voice_right_3
}


/**
 * 消息项ui操作接口
 */
interface OnMessageClickListener {
    fun onClick(m: Message): Boolean
    fun onDoubleClick(m: Message)
    fun onCopyClick(msg: Message)
    fun onDeleteClick(msg: Message)
}


/**
 * 语音输入的指示器
 */
@Composable
fun VoiceInputIndicator(
    indicatorState: Boolean,
    onCountFinish: () -> Unit
) {
    val countDownStart = 60

    // 计数器，按取模的值控制图标
    var voiceStateCount by remember {
        mutableStateOf(countDownStart)
    }


    var voiceInputIndicatorCounter: CountDownTimer? = null
    LaunchedEffect(key1 = Unit) {
        voiceInputIndicatorCounter = object : CountDownTimer(countDownStart * 1000L, 1000) {
            override fun onTick(millisUntilFinished: Long) {
                voiceStateCount -= 1
            }

            override fun onFinish() {
                onCountFinish()
            }
        }

        voiceInputIndicatorCounter?.start()
    }
    DisposableEffect(key1 = Unit) {
        onDispose {
            voiceInputIndicatorCounter?.cancel()
            voiceInputIndicatorCounter = null
        }
    }

    Box(
        Modifier
            .fillMaxSize()
            .clickable { }
    ) {
        Column(
            modifier = Modifier.align(Alignment.Center),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            if (voiceStateCount < 10) {
                Text(text = "${voiceStateCount}秒后停止录音")
                Spacer(modifier = Modifier.size(8.dp))
            }

            if (indicatorState) {
                ConstraintLayout(
                    modifier = Modifier
                        .size(126.dp)

                        .background(
                            color = colorResource(id = R.color.black_6),
                            shape = RoundedCornerShape(10.dp)
                        )
                ) {
                    val rVoice = createRef()
                    val rText = createRef()
                    val rAnim = createRef()
                    val baseLine = createGuidelineFromStart(0.6f)

                    Image(
                        painter = painterResource(id = R.drawable.ic_recording),
                        contentDescription = null,
                        modifier = Modifier
                            .constrainAs(rVoice) {
                                top.linkTo(parent.top, 34.dp)
                                end.linkTo(baseLine, 3.dp)
                            }
                            .size(38.dp))

                    Column(
                        verticalArrangement = Arrangement.Bottom,
                        modifier = Modifier.constrainAs(rAnim) {
                            start.linkTo(baseLine, 3.dp)
                            bottom.linkTo(rVoice.bottom)
                        }) {
                        Spacer(
                            modifier = Modifier
                                .size(width = 10.6.dp, height = 1.3.dp)
                                .background(colorResource(id = if (voiceStateCount % 4 > 3) R.color.white else R.color.black_6))
                        )
                        Spacer(modifier = Modifier.size(4.dp))
                        Spacer(
                            modifier = Modifier
                                .size(width = 8.6.dp, height = 1.3.dp)
                                .background(colorResource(id = if (voiceStateCount % 4 > 2) R.color.white else R.color.black_6))
                        )
                        Spacer(modifier = Modifier.size(4.dp))
                        Spacer(
                            modifier = Modifier
                                .size(width = 7.3.dp, height = 1.3.dp)
                                .background(colorResource(id = if (voiceStateCount % 4 > 1) R.color.white else R.color.black_6))
                        )
                        Spacer(modifier = Modifier.size(4.dp))
                        Spacer(
                            modifier = Modifier
                                .size(width = 6.dp, height = 1.3.dp)
                                .background(colorResource(id = if (voiceStateCount % 4 > 0) R.color.white else R.color.black_6))
                        )
                        Spacer(modifier = Modifier.size(4.dp))
                        Spacer(
                            modifier = Modifier
                                .size(width = 4.dp, height = 1.3.dp)
                                .background(colorResource(id = R.color.white))
                        )

                    }

                    Text(text = "手指上滑，取消发送",
                        fontSize = 11.sp,
                        color = colorResource(id = R.color.white),
                        modifier = Modifier.constrainAs(rText) {
                            centerHorizontallyTo(parent)
                            bottom.linkTo(parent.bottom, 19.dp)
                        })
                }
            } else {
                ConstraintLayout(
                    modifier = Modifier
                        .size(126.dp)
                        .background(
                            color = colorResource(id = R.color.color_cancel_voice),
                            shape = RoundedCornerShape(10.dp)
                        )
                ) {
                    val rVoice = createRef()
                    val rText = createRef()
                    Image(
                        painter = painterResource(id = R.drawable.ic_cancel_voice),
                        contentDescription = null,
                        modifier = Modifier
                            .constrainAs(rVoice) {
                                top.linkTo(parent.top, 34.dp)
                                centerHorizontallyTo(parent)
                            }
                            .size(38.dp))
                    Text(text = "松开手指，取消发送",
                        fontSize = 11.sp,
                        color = colorResource(id = R.color.white),
                        modifier = Modifier.constrainAs(rText) {
                            centerHorizontallyTo(parent)
                            bottom.linkTo(parent.bottom, 19.dp)
                        })
                }
            }
        }
    }
}


/**
 * 长按消息弹出选项
 */
@ExperimentalComposeUiApi
@Composable
fun MsgOption(
    msg: Message,       // 消息
    state: MutableState<Boolean>,
    alignment: Alignment,
    offset: IntOffset,
    onCopyClick: () -> Unit,
    onDeleteClick: () -> Unit,
) = Popup(
    alignment = alignment,
    offset = offset,
    onDismissRequest = { state.value = !state.value }
) {
    if (msg.contentType == MessageType.TEXT) {
        Box(
            modifier = Modifier
                .size(122.dp, 49.dp)
        ) {
            UImage(
                drawableId = R.drawable.ic_msg_opt, modifier = Modifier
                    .matchParentSize()
            )
            Row(
                modifier = Modifier
                    .matchParentSize(),
                verticalAlignment = Alignment.Top
            ) {
                UText(
                    text = "复制",
                    color = colorResource(id = R.color.white),
                    size = 13.sp,
                    contentPadding = PaddingValues(horizontal = 17.dp, vertical = 11.dp),
                    modifier = Modifier.clickable {
                        onCopyClick()
                    }
                )
                Spacer(
                    modifier = Modifier
                        .padding(vertical = 8.dp)
                        .width(0.33.dp)
                        .height(25.dp)
                        .background(colorResource(id = R.color.color_97))
                )
                UText(
                    text = "删除",
                    color = colorResource(id = R.color.white),
                    size = 13.sp,
                    contentPadding = PaddingValues(horizontal = 17.dp, vertical = 11.dp),
                    modifier = Modifier.clickable {
                    }
                )
            }
        }
    } else {
        Box(
            modifier = Modifier
                .size(61.dp, 49.dp)
        ) {
            UImage(
                drawableId = R.drawable.ic_msg_opt, modifier = Modifier
                    .matchParentSize()
            )
            Row(
                modifier = Modifier
                    .matchParentSize(),
                verticalAlignment = Alignment.Top
            ) {
                UText(
                    text = "删除",
                    color = colorResource(id = R.color.white),
                    size = 13.sp,
                    contentPadding = PaddingValues(horizontal = 17.dp, vertical = 11.dp),
                    modifier = Modifier.clickable {
                        onDeleteClick()
                    }
                )
            }
        }
    }
}